<?php


namespace App\Utils;


use Illuminate\Database\Eloquent\Builder;

/**
 * 查询辅助类
 * Class QueryHelper
 * @package App\Utils
 */
class QueryHelper
{
    /**
     * 范围唯一检查条件
     * @param Builder $query
     * @param int $start 开始值
     * @param int $end 结束值
     * @param string $startField 开始范围的数据库字段名称
     * @param string $endField 结束范围的数据库字段名称
     * @return Builder
     */
    static function onlyRange($query, $start, $end, $startField = 'start', $endField = 'end', $flag = '=')
    {
        $query->where(function (Builder $q) use ($start, $end, $startField, $endField, $flag) {
            $q->where(function (Builder $query) use ($start, $end, $startField, $flag) {
                $query->where($startField, ">" . $flag, $start);
                $query->where($startField, "<", $end);
            })->orWhere(function (Builder $query) use ($start, $end, $endField, $flag) {
                $query->where($endField, ">", $start);
                $query->where($endField, "<" . $flag, $end);
            })->orWhere(function (Builder $query) use ($start, $end, $startField, $endField, $flag) {
                $query->where($startField, "<" . $flag, $start);
                $query->where($endField, ">" . $flag, $end);
            });
            if (empty($flag)) {
                $q->orWhere(function (Builder $query) use ($start, $end, $startField, $endField) {
                    $query->where($startField, "=", $start);
                    $query->where($endField, "=", $end);
                });
            }
        });
        return $query;
    }

    /**
     * 范围唯一检查条件
     * @param Builder $query
     * @param int $start 开始值
     * @param int $end 结束值
     * @param string $startField 开始范围的数据库字段名称
     * @param string $endField 结束范围的数据库字段名称
     * @return Builder
     */
    static function onlyRangeRaw($query, $start, $end, $startField = 'start', $endField = 'end')
    {
        $query->whereRaw("($startField >= $start and $startField < $end) or ($endField > $start and $endField <= $end) or ($startField <= $start and $endField >= $end)");
        return $query;
    }

    /**
     * @param $query
     * @param $fields
     * @param $keyword
     * @param int $mode
     */
    static function like($query, $fields, $keyword, int $mode = 3)
    {
        $keyword = self::escapeLikeStr($keyword);
        $fields = explode('|', $fields);
        if ($mode == 1) {
            $keyword = '%' . $keyword;
        } else if ($mode == 2) {
            $keyword = $keyword . '%';
        } else {
            $keyword = "%$keyword%";
        }
        if (count($fields) == 1) {
            $query->where($fields[0], 'like', $keyword);
        } else {
            $query->where(function ($q) use ($fields, $keyword) {
                foreach ($fields as $field) {
                    $q->orWhere($field, 'like', $keyword);
                }
            });
        }
    }

    public static function escapeLikeStr($str)
    {
        $like_escape_char = '!';
        return str_replace([$like_escape_char, '%', '_'], [
            $like_escape_char . $like_escape_char,
            '\%',
            '\_',
        ], $str);
    }
}